home *** CD-ROM | disk | FTP | other *** search
-
- #include "appwin.h"
- #include "ui/label.h"
- #include "ui/point.h"
- #include "ui/xrbtngrp.h"
- #include "ui/toglbtn.h"
- #include "ui/containr.h"
- #include "ui/pushbtn.h"
- #include "ui/xrtglbtn.h"
- #include "ui/cntroler.h"
-
- enum {
- ID_CLEAR = 23, // View id of the "Clear" button
- ID_RADIX = 30, // View id of the radix selection box
- ID_DIGITS_BASE = 1, // First view id used by digits buttons
- ID_OPS_BASE = 100 // First view id used by operations buttons
- };
-
- const char* ops[] = {
- "+", "-", "*", "/", "%",
- #if defined(__MS_WINDOWS__)
- "&&",
- #else
- "&",
- #endif
- "|", ">>", "<<", "=", 0};
-
- const char digits[] = "0123456789ABCDEF";
-
- AppWindow::AppWindow ()
- : UI_Dialog (NULL, NULL, UI_Rectangle (50, 50, 400, 300))
- {
- Title() = "YACL Calculator";
- _op = '=';
- _top = 0;
- _stack[0] = 0;
- _stack[1] = 0;
-
- // Create the label
- _label = new UI_Label (this, UI_Rectangle (20, 5, 150, 25));
- _label->Title() = "0";
- _label->ShowBorder ();
- _label->SetTextStyle (UIText_Right);
-
- // Create the "Clear" button
- UI_PushButton* btn = new UI_PushButton
- (this, UI_Rectangle (30, 200, 60, 30), ID_CLEAR);
- btn->Title() = "Clear";
-
- UI_Rectangle result (40, 5, 150, 25);
- UI_Rectangle digitsPanel (10, 40, 140, 140);
- UI_Rectangle opsPanel (160, 40, 175, 70);
- UI_Rectangle radixRect (160, 110, 220, 180);
-
- MakeDigitButtons (digitsPanel); // Create the digit buttons
- MakeOpButtons (opsPanel); // Create the operations buttons
- MakeRadixPanel (radixRect); // Create the radix panel
-
- DoRadix (10); // Initial radix is decimal
- }
-
-
- void AppWindow::MakeDigitButtons (const UI_Rectangle& panel)
- {
- UI_PushButton* btn;
- UI_PointSequence seq = panel.RowMajor (35, 35);
- short n = seq.Size();
- for (short i = 0; i < n; i++) {
- UI_Rectangle shape (seq[i], 25, 25);
- btn = new UI_PushButton (this, shape, i + ID_DIGITS_BASE);
- btn->Title() = CL_String (digits[i], 1);
- }
- }
-
-
- void AppWindow::MakeOpButtons (const UI_Rectangle& panel)
- {
- UI_PushButton* btn;
- UI_PointSequence seq = panel.RowMajor (35, 35);
- for (short i = 0; ops[i] != 0; i++) {
- btn = new UI_PushButton (this, UI_Rectangle (seq[i], 25, 25),
- (UI_ViewID) (ID_OPS_BASE + ops[i][0])); // Map id's to operations
- btn->Title() = ops[i];
- }
- }
-
-
- void AppWindow::MakeRadixPanel (const UI_Rectangle& panel)
- {
- UI_ExOrButtonGroup* grp = new UI_ExOrButtonGroup (this, panel, ID_RADIX);
- grp->Title() = "Radix";
- UI_ExOrToggleButton* xor_btn;
- UI_PointSequence seq = UI_Rectangle (15, 25, 210, 140).RowMajor (50, 30);
- for (short i = 2; i <= 16; i++) {
- UI_Rectangle shape (seq[i-2], 45, 25);
- xor_btn = new UI_ExOrToggleButton (grp, shape, i + ID_RADIX);
- xor_btn->Title() = CL_String (i);
- }
- grp->Selection() = ID_RADIX + 10; // Decimal
- }
-
-
- bool AppWindow::HandleChildEvent (const UI_Event& e)
- {
- UI_Dialog::HandleChildEvent (e);
- if (e.Type() == Event_KeyTyped) {
- short key = e.Key();
- bool b = (key >= '0' && key < _radix + '0')
- ? DoDigit (key - '0')
- : DoOp (key);
- // if (!b)
- // _Controller->Beep();
- return TRUE;
- }
- if (e.Type() != Event_Select)
- return FALSE;
- UI_VisualObject& origin = *(e.Origin());
- UI_ViewID id = origin.ViewID();
- if (id == ID_RADIX) { // User changed the current radix
- short radix = ((UI_ExOrButtonGroup*) (*this)[ID_RADIX])
- ->Selection() - ID_RADIX;
- DoRadix (radix);
- }
- else if (id == ID_CLEAR) { // User clicked the Clear button
- DoClear();
- return TRUE;
- }
- else if (id >= ID_DIGITS_BASE && id < ID_DIGITS_BASE + 16)
- // User clicked on a digit button
- DoDigit (id - ID_DIGITS_BASE);
- else // User clicked on an operation button
- DoOp (id - ID_OPS_BASE);
- return TRUE;
- }
-
-
- void AppWindow::DoRadix (short radix)
- {
- _radix = radix;
- _label->Title() = CL_Integer(_stack[_top]).InRadix (_radix);
- // Enable the appropriate buttons
- short i;
- for (i = 0; i < _radix; i++)
- (*this)[i+ID_DIGITS_BASE]->Enable();
- for (i = _radix; i < 16; i++)
- (*this)[i+ID_DIGITS_BASE]->Disable();
- }
-
-
- void AppWindow::DoClear ()
- {
- _top = 0;
- _stack[0] = 0;
- _label->Title() = "0";
- }
-
- bool AppWindow::DoDigit (short digit)
- {
- _stack[_top] = _stack[_top] * _radix + digit;
- _label->Title() = CL_Integer(_stack[_top]).InRadix (_radix);
- return TRUE;
- }
-
-
- bool AppWindow::DoOp (char op)
- {
- if (op != '+' && op != '-' && op != '*' && op != '/' && op != '%'
- && op != '<' && op != '>' && op != '&' && op != '|' && op != '=')
- return FALSE;
- if (op != '=' && _top == 0) {
- _top = 1;
- _op = op;
- _stack[_top] = 0;
- _label->Title() = "0";
- return TRUE;
- }
- switch (_op) {
- case '+': _stack[_top-1] += _stack[_top]; break;
-
- case '-': _stack[_top-1] -= _stack[_top]; break;
-
- case '*': _stack[_top-1] *= _stack[_top]; break;
-
- case '/': _stack[_top-1] /= _stack[_top]; break;
-
- case '%': _stack[_top-1] %= _stack[_top]; break;
-
- case '&': _stack[_top-1] &= _stack[_top]; break;
-
- case '|': _stack[_top-1] |= _stack[_top]; break;
-
- case '>': _stack[_top-1] >>= _stack[_top]; break;
-
- case '<': _stack[_top-1] <<= _stack[_top]; break;
-
- case '=': if (_top == 1)
- _stack[_top-1] = _stack[_top--];
- break;
-
- default: return FALSE;
- };
-
- if (op == '=') {
- _top = 0;
- }
- else {
- _top = 1;
- _stack[_top] = 0;
- }
- _op = op;
- _label->Title() = CL_Integer (_stack[0]).InRadix (_radix);
- return TRUE;
- }
-